import jsSHA from 'jssha'
import type { FetchError } from 'ofetch'
import { UploadRawFile } from 'element-plus'
import { _AsyncData } from 'nuxt/dist/app/composables/asyncData'

export const state = () => {
    const siteConfig = useSiteConfig()
    return siteConfig.upload.mode == 'local' ? 'disable' : 'enable'
}

export async function fileUpload<DataT = any>(fd: FormData, params: anyObj = {}): Promise<_AsyncData<ApiResponse<DataT>, FetchError | null>> {
    const siteConfig = useSiteConfig()
    const file = fd.get('file') as UploadRawFile
    const sha1 = await getFileSha1(file)
    const fileKey = getSaveName(file, sha1)
    fd.append('key', fileKey)
    for (const key in siteConfig.upload.params) {
        fd.append(key, siteConfig.upload.params[key])
    }
    // 接口要求file排在最后
    fd.delete('file')
    fd.append('file', file)

    const { error } = await Http.fetch({
        url: siteConfig.upload.url,
        method: 'POST',
        body: fd,
        params: params,
    })

    if (!error.value) {
        const fileUrl = '/' + fileKey
        Http.fetch({
            url: '/api/Alioss/callback',
            method: 'POST',
            body: {
                url: fileUrl,
                name: file.name,
                size: file.size,
                type: file.type,
                sha1: sha1,
            },
        })
        const res = {
            code: 1,
            data: {
                file: {
                    full_url: fullUrl(fileUrl),
                    url: fileUrl,
                },
            },
            msg: '',
            time: Date.now(),
        }
        return Promise.resolve({ data: ref(res) } as unknown as _AsyncData<ApiResponse<DataT>, FetchError | null>)
    }
    return Promise.reject(error.value)
}

export function getSaveName(file: UploadRawFile, sha1: string) {
    const fileSuffix = file.name.substring(file.name.lastIndexOf('.') + 1)
    const fileName = file.name.substring(0, file.name.lastIndexOf('.'))
    const dateObj = new Date()

    const replaceArr: anyObj = {
        '{topic}': 'default',
        '{year}': dateObj.getFullYear(),
        '{mon}': ('0' + (dateObj.getMonth() + 1)).slice(-2),
        '{day}': dateObj.getDate(),
        '{hour}': dateObj.getHours(),
        '{min}': dateObj.getMinutes(),
        '{sec}': dateObj.getSeconds(),
        '{random}': shortUuid(),
        '{random32}': randomNum(32, 32),
        '{filename}': fileName.substring(0, 15),
        '{suffix}': fileSuffix,
        '{.suffix}': '.' + fileSuffix,
        '{filesha1}': sha1,
    }
    const replaceKeys = Object.keys(replaceArr).join('|')
    const siteConfig = useSiteConfig()

    const savename = siteConfig.upload.savename[0] == '/' ? siteConfig.upload.savename.slice(1) : siteConfig.upload.savename

    return savename.replace(new RegExp(replaceKeys, 'gm'), (match) => {
        return replaceArr[match]
    })
}

async function getFileSha1(file: UploadRawFile) {
    const shaObj = new jsSHA('SHA-1', 'ARRAYBUFFER')
    shaObj.update(await file.arrayBuffer())
    return shaObj.getHash('HEX')
}
